package cn.coder.easyjson;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.coder.easyjson.stream.JSONReader;
import cn.coder.easyjson.stream.JSONWrapper;
import cn.coder.easyjson.util.Assert;
import cn.coder.easyjson.util.ObjectUtils;

public class JSON {

	public static <T> T parse(Object obj, Class<T> clazz) {
		return parseObject(obj).parse(clazz);
	}

	public static boolean validArray(String str) {
		return str.startsWith("[") && str.endsWith("]");
	}

	public static boolean validObject(String str) {
		return str.startsWith("{") && str.endsWith("}");
	}

	@SuppressWarnings("rawtypes")
	public static JSONObject parseObject(Object obj) {
		Assert.notNull(obj);
		if (obj instanceof CharSequence) {
			final String str = obj.toString().trim();
			return (JSONObject) new JSONReader().read(str);
		}
		if (obj instanceof Map) {
			return new JSONObject((Map) obj);
		}
		if (ObjectUtils.isSimpleBean(obj)) {
			final JSONWrapper wrapper = new JSONWrapper(obj);
			return wrapper.fromBean();
		}
		throw new RuntimeException("Unsupported object:" + obj.getClass());
	}

	public static JSONArray parseArray(Object obj) {
		Assert.notNull(obj);
		if (obj instanceof CharSequence) {
			final String str = obj.toString().trim();
			return (JSONArray) new JSONReader().read(str);
		}
		if (obj instanceof Collection) {
			return new JSONArray((Collection<?>) obj);
		}
		if (obj.getClass().isArray()) {
			int len = Array.getLength(obj);
			final JSONArray array = new JSONArray(len);
			for (int i = 0; i < len; i++) {
				array.set(i, Array.get(obj, i));
			}
			return array;
		}
		throw new RuntimeException("Unsupported array");
	}

	public static <T> List<T> parseArray(Object obj, Class<T> clazz) {
		return parseArray(obj).parse(clazz);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <K, V> Map<K, V> parseMap(Object obj, Class<K> k, Class<V> v) {
		Map<String, Object> map = parseObject(obj).getInnerMap();
		if (map != null) {
			Set<String> keys = map.keySet();
			Map temp = new HashMap<K, V>();
			for (Object key : keys) {
				temp.put(ObjectUtils.cast(k, key), ObjectUtils.cast(v, map.get(key)));
			}
			return temp;
		}
		return null;
	}

	public static String toJSON(Object obj) {
		Assert.notNull(obj);
		if (obj instanceof CharSequence) {
			return obj.toString().trim();
		}
		if (obj instanceof Map) {
			return parseObject(obj).toJson();
		}
		if (obj instanceof Collection) {
			return parseArray(obj).toJson();
		}
		if (obj.getClass().isArray()) {
			return parseArray(obj).toJson();
		}
		if (ObjectUtils.isSimpleBean(obj)) {
			return parseObject(obj).toJson();
		}
		throw new RuntimeException("Unsupported object:" + obj.getClass());
	}
}
